#include"common.hpp"
#include"Log.hpp"
#include"Socket.hpp"
#include<sys/select.h>


class SeletServer{
    const static int defaultfd = -1;
    const static int size = sizeof(fd_set)*8;
public:
    SeletServer(int port)
    :_server(std::make_unique<TcpSocket>())
    ,_isrunning(false)
    {
        _server->BuideTcpSocket(port);

        fdarr = (int*)malloc(sizeof(int)*size);
        for(int i = 0;i < size; i++){
            fdarr[i] = defaultfd;
        }
        fdarr[0] = _server->Getfd();

    }   

    void Accept(){
        Inetaddr iaddr;
        int tmpsock = _server->Accept(&iaddr);
        for(int i = 0;i < size;i++){
            if(fdarr[i] == defaultfd)
            {
                fdarr[i] = tmpsock;
                break;
            }
        }

    }
    void Recv(int pos){
        char buff[1024];
        int size = recv(fdarr[pos],buff,sizeof(buff)-1,0);
        if(size > 0){
            buff[size] = 0;
            std::cout<<buff<<std::endl;
        }
        else if(size == 0){
            close(fdarr[pos]);
            fdarr[pos] = defaultfd;
            LOG(level::DEBUG)<<"exit...";
        }
        else{
            close(fdarr[pos]);
            fdarr[pos] = defaultfd;
            LOG(level::ERROR)<<"recv ERR";
        }
    }
    void Dispatch(fd_set& fset){

        for(int i = 0;i < size; i++){
            if(fdarr[i] == defaultfd)
                continue;
            
            if(FD_ISSET(fdarr[i],&fset)){
                if(fdarr[i] == _server->Getfd())
                {
                    Accept();
                }
                else{
                    Recv(i);
                }
            }
            
        }
        
    }

    void start(){
        _isrunning = true;
        while(_isrunning){
            // struct timaval* tv = nullptr;
            
            fd_set fs;
            FD_ZERO(&fs);
            int maxfd = -1;
            for(int i = 0;i < size;i++){
                if(fdarr[i] == defaultfd)
                    continue;
                FD_SET(fdarr[i],&fs);
                if(maxfd < fdarr[i])
                {
                    maxfd = fdarr[i];
                }
            }

            int ret = select(maxfd+1,&fs,nullptr,nullptr,nullptr);
            switch (ret)
            {
            case -1:
                LOG(level::WARING)<<"select fail";
                break;
            case 0:
                LOG(level::DEBUG)<<"timeout..";
                break;
            default:
                Dispatch(fs);
                break;
            }

        }
        _isrunning = false;
    }

    void Stop()
    {
        _isrunning = false;
    }

    ~SeletServer(){}
private:
    std::unique_ptr<Socket> _server;
    bool _isrunning;

    int* fdarr;
};